﻿using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using PowersourceUIToolkit;
using UCL.Powersource.Analysis;
using System.Threading;
namespace UCL.Powersource.TFS
{
    public static class PackageConfigurationLoader
    {
        private static ILog _Log;

        private static ILog Log
        {
            get
            {
                if (_Log == null) _Log = LogManager.GetLog(typeof(PackageConfigurationLoader));
                return _Log;
            }
        }

        static IPowersourceExt _IPowersourceExt;
        static IPowersourceExt IPowersourceExt
        {
            get { return _IPowersourceExt ?? (_IPowersourceExt = PowersourceConnector.GetExtensibilityPoint()); }
        }

        private static IEnumerable<Type> _KnownTypes;
        static IEnumerable<Type> KnownTypes
        {
            get
            {
                if (_KnownTypes == null)
                {
                    var kt = new List<Type>();
                    kt.AddRange(IPowersourceExt.StatisticManager.AvailableStatisticTypes);
                    kt.AddRange(IoC.GetDefaultInterfaceImplementationTypes());
                    _KnownTypes = kt.Distinct();
                }

                return _KnownTypes;
            }
        }


        public static void Save(IPackageConfiguration ipcc, string fileName)
        {
            Save(ipcc, fileName, KnownTypes);
        }

        private static void Save(IPackageConfiguration ipcc, string fileName, IEnumerable<Type> knownTypes)
        {
            if (ipcc != null)
            {
                ipcc.TeamProjectCollectionStatistics.MergeResultsFromStatisticManager();
                int e = 0;
                while (e < 10)
                {
                    try
                    {
                        using (FileStream stream = File.Open(fileName, FileMode.Create))
                        {
                            DataContractSerializer formatter = new DataContractSerializer(ipcc.GetType(), knownTypes);
                            formatter.WriteObject(stream, ipcc);
                            break;
                        }
                    }
                    catch (Exception exc)
                    { e++; Log.Warn(exc, "Save error"); Thread.Sleep(500); }
                }
            }
            else
                Log.Warn("SaveTfsTeamProjectCollectionConfigurations called with null configuration.");

        }

        public static IPackageConfiguration Load(string fileName)
        {
            return Load(fileName, KnownTypes);
        }
        private static IPackageConfiguration Load(string fileName, IEnumerable<Type> knownTypes)
        {
            var concreteConfig = IoC.Get<IPackageConfigurationFactory>().Create();
            try
            {
                if (File.Exists(fileName))     //If the configuration file for stat project collections exist, open the configuration file for stat project collections and load tfs stat project collection configurations
                {
                    using (FileStream stream = File.Open(fileName, FileMode.Open))
                    {
                        DataContractSerializer formatter = new DataContractSerializer(concreteConfig.GetType(), knownTypes);
                        var loadedConfig = (IPackageConfiguration)formatter.ReadObject(stream);
                        var mngr = IoC.Get<IStatisticManager>();
                        mngr.LoadResultsFromStatisticResultsCollection(loadedConfig.TeamProjectCollectionStatistics);
                        return loadedConfig;
                    }
                }
                Log.Info("{0} config file does not exist, using default configuration", fileName);
                return concreteConfig;
            }
            catch (Exception exc)
            {
                Log.Error(exc, "Cannot deserialize stat project collection configuration object, using default settings");
                return concreteConfig;
            }
        }
    }

    public interface IPackageConfiguration
    {
        void MergeWithCollection(ITfsTeamProjectCollection collection);

        IStatisticCollectionWithResults TeamProjectCollectionStatistics { get; }
        IReadOnlyList<ITfsTeamProjectCollectionConfiguration> TFSTeamCollectionConfigurations { get; }

        string DefaultIldasmPath { get; }
        string DefaultLocalDropBasePath { get; }
        string DefaultCodeIndexDBServer { get; }
        string DefaultExportPath { get; }
        string CreateDefaultWebServiceUrl(string collectionUrl);
    }
}
